import sys
import serial
import threading
import queue
import time
import serial.tools.list_ports
from PyQt5 import QtWidgets,QtGui
from PyQt5.QtWidgets import QMessageBox
from PyQt5.QtCore import QObject , pyqtSignal,Qt,QTimer
from setting import Ui_Dialog
from main_window import Ui_MainWindow
from SNcode import SNcode
from factory_test_result import factory_test_result

class Pyqt5_Serial(QtWidgets.QDialog, Ui_Dialog):
    mt2523Signal = pyqtSignal(str)
    messageSignal = pyqtSignal(str, str)
    def __init__(self):
        super(Pyqt5_Serial, self).__init__()

        self.setupUi(self)
        self.init()
        self.setWindowTitle("Serial port settings")
        self.ser = serial.Serial()
        self.ser2 = serial.Serial()
        self.port_check()

        self.data_num_received = 0
        self.data_num_sended = 0
    def init(self):

        self.s1__box_1.clicked.connect(self.port_check)

        self.s1__box_2.currentTextChanged.connect(self.port_imf)

        self.open_button.clicked.connect(self.port_open)

        self.close_button.clicked.connect(self.port_close)

        self.timer = QTimer(self)
        self.timer.timeout.connect(self.data_receive)

    def port_check(self):
        self.Com_Dict = {}
        port_list = list(serial.tools.list_ports.comports())
        self.s1__box_2.clear()
        for port in port_list:
            self.Com_Dict["%s" % port[0]] = "%s" % port[1]
            self.s1__box_2.addItem(port[1])

        if len(self.Com_Dict) == 0:
            self.state_label.setText(" 无串口")

    # 串口信息
    def port_imf(self):
        # 显示选定的串口的详细信息
        imf_s = self.s1__box_2.currentText()
        if imf_s != "":
            self.state_label.setText(self.s1__box_2.currentText())
            pass

    # 打开串口
    def port_open(self):
        self.ser.port = self.s1__box_2.currentText()

        ######################通过键值查找键 ######################
        key_list = []
        value_list = []

        for key, value in self.Com_Dict.items():
            key_list.append(key)
            value_list.append(value)

        get_value =self.s1__box_2.currentText()
        if get_value in value_list:
            get_value_index = value_list.index(get_value)
            print("你要查询的值对应的键为：%s" % key_list[get_value_index])
            self.ser.port = key_list[get_value_index]
        else:
            print("你要查询的值%s不存在" % get_value)
        ######################通过键值查找键 ######################

        self.ser.baudrate = int(self.s1__box_3.currentText())
        self.ser.bytesize = int(self.s1__box_4.currentText())
        self.ser.stopbits = int(self.s1__box_6.currentText())
        self.ser.parity = self.s1__box_5.currentText()
        self.ser.timeout = 0.02
        try:
            self.ser.open()
        except:
            QMessageBox.critical(self, "Port Error", "此串口不能被打开！")
            return None
        self.timer.start(2)
        if self.ser.isOpen():
            self.open_button.setEnabled(False)
            self.close_button.setEnabled(True)
    # 关闭串口
    def port_close(self):
        self.timer.stop()
        try:
            self.ser.close()
        except:
            pass
        self.open_button.setEnabled(True)
        self.close_button.setEnabled(False)

    # 发送数据
    def data_send(self):
        if self.ser.isOpen():
            input_s = self.s3__send_text.toPlainText()
            if input_s != "":
                # 非空字符串
                if self.hex_send.isChecked():
                    # hex发送
                    input_s = input_s.strip()
                    send_list = []
                    while input_s != '':
                        try:
                            num = int(input_s[0:2], 16)
                        except ValueError:
                            QMessageBox.critical(self, 'wrong data', '请输入十六进制数据，以空格分开!')
                            return None
                        input_s = input_s[2:].strip()
                        send_list.append(num)
                    input_s = bytes(send_list)
                else:
                    # ascii发送
                    input_s = (input_s + '\r\n').encode('utf-8')

                num = self.ser.write(input_s)
                self.data_num_sended += num
                self.lineEdit_2.setText(str(self.data_num_sended))
        else:
            pass

    def data_send_AT(self,input_s):
        if self.ser.isOpen():
            if input_s != "":
                input_s = (input_s + '\r\n').encode('utf-8')
                try:
                    self.ser.write(input_s)
                    return "ok"
                except ValueError:
                    return "false"
        else:
            return "false"
            pass
    def data_receive(self):
        try:
            num = self.ser.inWaiting()
        except:
            self.port_close()
            return None
        if num > 0:
            data = self.ser.read_all()
            if(data[0] != 0):
                print("data_receive :" + data.decode('iso-8859-1'))
                try:
                    self.mt2523Signal.emit(data.decode('iso-8859-1'))  # 发射信号
                except:
                    print('任务  self.mt2523Signal.emit(data.decode  失败')
                    return None


        else:
            pass
#from enum import Enum
#state = Enum("state", ("connect", "ReadCode", "SweepCode ", "WriteSncode","WriteSncode","FactoryTesting"))

class main(QtWidgets.QMainWindow, Ui_MainWindow ):


    #连接状态
    barcodeSignal = pyqtSignal(str)
    messageSignal = pyqtSignal(str, str)
    progressBarSignal = pyqtSignal(int)
    lableSignal = pyqtSignal(str)
    def __init__(self):
        super(main, self).__init__()
        self.setupUi(self)
        self.init()
        self.setWindowTitle("Yanhe serial port upper computer")

        SNcode.__init__(self)
        factory_test_result.__init__(self)

        self.icon = QtGui.QIcon()

        #在自己的 窗口定义一个子窗口
        self.show()
        self.setting = Pyqt5_Serial()
        self.setting.exec()
        #一些变量
        self.string = ""
        self.time_now = 0
        self.oldtime = 0
        #消息队列

        self.Mainthreadqueue = queue.Queue(maxsize=1)  # 主线程队列

        self.receivedconnectionmessagequeue = queue.Queue(maxsize=1)  # 接收到连接消息队列
        self.receivedsncodemessagequeue = queue.Queue()  # 获取到SN号
        self.writesncodeokmessagequeue = queue.Queue()  # 写入SN号成功的信号
        self.factoryresultqueue = queue.Queue()  # 收到工厂测试结果
        self.mt2523abnormalqueue = queue.Queue()  # 异常出现信号

        self.GettheSNnumber = queue.Queue()
        #主线程
        self.Mainthread = threading.Thread(target=self.Mainthread)
        self.Mainthread.setDaemon(True)
        self.Mainthread.start()

        #信号量
        #设置页面
        self.setting.mt2523Signal.connect(self.getMt2523Signal)
        self.setting.messageSignal.connect(self.show_message)

        #主页面
        self.progressBarSignal.connect(self.show_progressBar)   #进度条
        self.barcodeSignal.connect(self.getBarcodeSignal)       #扫码枪 扫描到sn号后发送
        self.messageSignal.connect(self.show_message)           #显示错误 正确提示窗
        self.lableSignal.connect(self.show_lable)
        #按键消息
        self.pushButton_2.clicked.connect(lambda:self.setting.exec())
        self.pushButton.clicked.connect(lambda:self.Mainthreadqueueput("connect"))

    def Mainthreadqueueput(self,strin):
        try:
            self.Mainthreadqueue.put(strin, block=False, timeout=0)
        except queue.Full:
            print('任务 Mainthreadqueueput 队列已满，写入失败')
        pass
 
    def Mainthread(self):
        while True:
            self.str = ""
            self.str =self.Mainthreadqueue.get()  # 获得sn号
            print(f"Mainthreadqueue = {self.str}")
            if self.str == "connect":
                self.lableSignal.emit("连接手表中..")
                self.progressBarSignal.emit(10)  # 发射信号
                self.Connection_check()
            elif self.str == "ReadCode":
                self.lableSignal.emit("读取sn号中")

                self.progressBarSignal.emit(25)  # 发射信号
                self.get_sncode()
            elif self.str == "SweepCode":
                self.lableSignal.emit("请扫码。。")
                self.progressBarSignal.emit(40)  # 发射信号
                self.sweep_sncode()
            elif self.str == "WriteSncode":
                self.lableSignal.emit("写入sn号中。。。")
                self.progressBarSignal.emit(55)  # 发射信号
                self.write_sncode()
            elif self.str == "FactoryTesting":
                self.lableSignal.emit("保持连接 请在手表端进行工厂测试")
                self.progressBarSignal.emit(70)  # 发射信号
                #self.FactoryTesting()
                pass
    def show_progressBar(self, num):
        self.progressBar.setProperty("value", 1+ num)
    def show_message(self, Error,str):
        if Error == "错误":
            self.lableSignal.emit("请重新尝试")
            self.progressBarSignal.emit(1)  # 发射信号
        QMessageBox.critical(self, Error, str)
    def show_lable(self,str):
        self.label_2.setText(str)
    def getMt2523Signal(self, data):
        print(F"data=   ：{data}")
        #收到查询联通应答
        if -1!=data.find("OK"):
            try:
                self.receivedconnectionmessagequeue.put(data, block=False, timeout=0)
            except queue.Full:
                print('任务 receivedconnectionmessagequeue 队列已满，写入失败')
            pass

        #收到查询sn号
        if -1!=data.find("SN_GET"):
            try:
                self.receivedsncodemessagequeue.put(data, block=False, timeout=0)
            except queue.Full:
                print('任务 receivedsncodemessagequeue 队列已满，写入失败')
            pass

        #收到写入sn号应答
        if -1!=data.find("SN_SET"):
            try:
                self.writesncodeokmessagequeue.put(data, block=False, timeout=0)
            except queue.Full:
                print('任务 writesncodeokmessagequeue 队列已满，写入失败')
            pass

        #收到写入sn号应答
        if -1!=data.find("FACTORY_RESULT"):
            try:
                self.factoryresultqueue.put(data, block=False, timeout=0)
            except queue.Full:
                print('任务 factoryresultqueue 队列已满，写入失败')
            pass
    def getBarcodeSignal(self,data):
        print(F"SN={data}")
        if len(data) >= 16:
            self.GettheSNnumber.put(data)
        else :
            self.messageSignal.emit("错误", "二维码错误")
            self.Mainthreadqueue.put("SweepCode")
            pass
    def  FactoryTesting(self):
        while True :

            self.factoryresulstr = self.factoryresultqueue.get()
            #空列表

            try:
                self.factoryresulstr = (self.factoryresulstr.split("="))[1]
            except:
                print("数据来源错误")
                pass

            self.factoryresullist =  self.factoryresulstr.split(",")

            self.factoryresul_Dict = {}
            for iterm in self.factoryresullist:
                try:
                    self.factoryresul_Dict[iterm.split(":")[0]] = iterm.split(":")[1]
                except:
                    print("串口数据错误")
                    pass
            #清空列表
            self.factoryresulexcel_list = []

            #添加时间
            self.factoryresulexcel_list.append(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()))
            if 'SN' in self.factoryresul_Dict.keys():  #
                self.factoryresulexcel_list.append(self.factoryresul_Dict["SN"])
            else :
                self.factoryresulexcel_list.append(" ")
            if 'SDNAND' in self.factoryresul_Dict.keys():
                self.factoryresulexcel_list.append(self.factoryresul_Dict["SDNAND"])
            else :
                self.factoryresulexcel_list.append(" ")

            if 'AFE4410' in self.factoryresul_Dict.keys():
                self.factoryresulexcel_list.append(self.factoryresul_Dict["AFE4410"])
            else :
                self.factoryresulexcel_list.append(" ")
            if 'ICM40607' in self.factoryresul_Dict.keys():
                self.factoryresulexcel_list.append(self.factoryresul_Dict["ICM40607"])
            else :
                self.factoryresulexcel_list.append(" ")
            if 'ELECTRIC_MACHINERY' in self.factoryresul_Dict.keys():
                self.factoryresulexcel_list.append(self.factoryresul_Dict["ELECTRIC_MACHINERY"])
            else :
                self.factoryresulexcel_list.append(" ")

            if 'CHARGE' in self.factoryresul_Dict.keys():
                self.factoryresulexcel_list.append(self.factoryresul_Dict["CHARGE"])
            else :
                self.factoryresulexcel_list.append(" ")

            if 'POWER_WASTE' in self.factoryresul_Dict.keys():
                self.fself.actoryresulexcel_list.append(self.factoryresul_Dict["POWER_WASTE"])
            else :
                self.factoryresulexcel_list.append(" ")

            if 'BLUETOOTH' in self.factoryresul_Dict.keys():
                self.factoryresulexcel_list.append(self.factoryresul_Dict["BLUETOOTH"])
            else :
                self.factoryresulexcel_list.append(" ")

            #写入sn号
            factory_test_result.add_factory_result(self.factoryresulexcel_list)

            print("写入测量结果")
            self.progressBarSignal.emit(99)  # 发射信号
            #self.messageSignal.emit("成功", "测量结果到表格中成功")

    #进入sn扫码输入阶段
    def sweep_sncode(self):
        self.sncode = ""
        print("测试人员请扫码")
        try:
            self.sncode = self.GettheSNnumber.get(timeout=20)  # 获得对象.
            print("扫码到SN号 ")
            self.Mainthreadqueue.put("WriteSncode")
            # Opt 1: Handle task here and call q.task_done()
        except:
            pass

    def write_sncode(self):
        if self.setting.data_send_AT(  "AT+ENVDM=SN_SET:" +  self.sncode) == "ok":
            print("write_sncode 写入完成")
            pass
        else:
            print("串口连接失败")
            self.messageSignal.emit("错误", "串口未连接")
            return
        self.data = ""
        self.writesncodeokmessagequeue.queue.clear()
        print("开始写入SN号")
        try:
            self.data = self.writesncodeokmessagequeue.get(timeout=2)  # 获得对象.
            print("SN写入成功 ")

            print("sn已号收录到表格中 ")
            #进入工厂测试阶段
            self.Mainthreadqueue.put("FactoryTesting")
            # Opt 1: Handle task here and call q.task_done()
        except :
            # Handle empty queue here

            print("SN写入失败")
            self.messageSignal.emit("错误", "SN号写入失败")
            pass
    def get_sncode(self):
        self.receivedsncodemessagequeue.queue.clear()
        if self.setting.data_send_AT("AT+ENVDM=SN_GET") == "ok":
            print("串口连接成功")
            pass
        else:
            self.messageSignal.emit("错误", "串口未连接")
            print("串口未连接")
            return
        self.data = ""
        try:
            self.data = self.receivedsncodemessagequeue.get(timeout=5)  # 获得对象.

            print(" self.data = " + self.data)
            if self.data.find("SN_GET:ERROR_CODE") > -1 :
                print("find  SN_GET")
                if self.data.find("SN_GET:ERROR_CODE:1") > -1 :
                    print("没有sn号")
                    # 进入sn烧录模式
                    self.Mainthreadqueue.put("SweepCode")
                    pass
                if self.data.find("SN_GET:ERROR_CODE:0") > -1 :
                    #进入异常处理 芯片损坏
                    self.messageSignal.emit("错误", "nvdm读取错误")
                    pass

            else:
                #sn号16位
                if(len(self.data) == 23 ):
                    print(f"查询到sn号 sn号 = {self.data[7:]}")
                    self.Mainthreadqueue.put("FactoryTesting")
        except :
            # Handle empty queue here
            print("获取反馈超时")
            self.messageSignal.emit("错误", "收不到mt2523反馈")
            pass
    def Connection_check(self):
        print("开始发送连接测试")
        self.receivedconnectionmessagequeue.queue.clear()
        if self.setting.data_send_AT("AT+TESTCMD=?")=="ok" :
            print("串口连接成功")
            pass
        else:
            print("串口连接失败")
            self.messageSignal.emit("错误", "串口未连接")
            return
        #等待消息到来
        self.data = ""
        try:
            self.data = self.receivedconnectionmessagequeue.get(timeout=1)  # 获得对象.
            print("收到信号")
            self.Mainthreadqueue.put("ReadCode")
            pass
        except :
            # Handle empty queue here
            print("没有收到信号")
            self.messageSignal.emit("错误","手表连接失败")
            pass


    def init(self):
        pass
    def keyPressEvent(self, QKeyEvent):  # 键盘某个键被按下时调用
        # 参数1  控件
        self.time_now = int(round(time.time() * 1000))
        print(F"time = {self.time_now - self.oldtime}")
        #盘点两次按键的时间间隔 如果大于30ms 则清空字符串
        if self.time_now - self.oldtime > 30:
            self.string = ""
        self.oldtime = self.time_now
        if QKeyEvent.key() == Qt.Key_Return:
            self.label.setText("SN号 = "+ self.string)
            self.progressBar.setProperty("value", 100)
            self.barcodeSignal.emit((self.string+"\r\n").encode('UTF-8').decode('iso-8859-1'))  # 发射信号
            print(f"{self.string}")
            pass
        if QKeyEvent.key() <= 1000:
            self.string = self.string + chr(QKeyEvent.key())
if __name__ == '__main__':
    app = QtWidgets.QApplication(sys.argv)
    main = main()
    main.show()
    sys.exit(app.exec_())
